Merge pull request #1340 from cantino/post_agent_downcase_response_headers

 Downcase header names in Events that PostAgent emits

Akinori MUSHA 8 years ago
parent
commit
4280bdc5e0

+ 41 - 1
app/models/agents/post_agent.rb

@@ -25,6 +25,13 @@ module Agents
25 25
 
26 26
       If `emit_events` is set to `true`, the server response will be emitted as an Event and can be fed to a WebsiteAgent for parsing (using its `data_from_event` and `type` options). No data processing
27 27
       will be attempted by this Agent, so the Event's "body" value will always be raw text.
28
+      The Event will also have a "headers" hash and a "status" integer value.
29
+      Set `event_headers_style` to one of the following values to normalize the keys of "headers" for downstream agents' convenience:
30
+
31
+        * `capitalized` (default) - Header names are capitalized; e.g. "Content-Type"
32
+        * `downcased` - Header names are downcased; e.g. "content-type"
33
+        * `snakecased` - Header names are snakecased; e.g. "content_type"
34
+        * `raw` - Backward compatibility option to leave them unmodified from what the underlying HTTP library returns.
28 35
 
29 36
       Other Options:
30 37
 
@@ -92,6 +99,12 @@ module Agents
92 99
         errors.add(:base, "if provided, emit_events must be true or false")
93 100
       end
94 101
 
102
+      begin
103
+        normalize_response_headers({})
104
+      rescue ArgumentError => e
105
+        errors.add(:base, e.message)
106
+      end
107
+
95 108
       unless %w[post get put delete patch].include?(method)
96 109
         errors.add(:base, "method must be 'post', 'get', 'put', 'delete', or 'patch'")
97 110
       end
@@ -124,6 +137,29 @@ module Agents
124 137
 
125 138
     private
126 139
 
140
+    def normalize_response_headers(headers)
141
+      case interpolated['event_headers_style']
142
+      when nil, '', 'capitalized'
143
+        normalize = ->name {
144
+          name.gsub(/(?:\A|(?<=-))([[:alpha:]])|([[:alpha:]]+)/) {
145
+            $1 ? $1.upcase : $2.downcase
146
+          }
147
+        }
148
+      when 'downcased'
149
+        normalize = :downcase.to_proc
150
+      when 'snakecased', nil
151
+        normalize = ->name { name.tr('A-Z-', 'a-z_') }
152
+      when 'raw'
153
+        normalize = ->name { name }  # :itself.to_proc in Ruby >= 2.2
154
+      else
155
+        raise ArgumentError, "if provided, event_headers_style must be 'capitalized', 'downcased', 'snakecased' or 'raw'"
156
+      end
157
+
158
+      headers.each_with_object({}) { |(key, value), hash|
159
+        hash[normalize[key]] = value
160
+      }
161
+    end
162
+
127 163
     def handle(data, payload = {})
128 164
       url = interpolated(payload)[:post_url]
129 165
       headers = headers()
@@ -156,7 +192,11 @@ module Agents
156 192
       }
157 193
 
158 194
       if boolify(interpolated['emit_events'])
159
-        create_event payload: { body: response.body, headers: response.headers, status: response.status }
195
+        create_event payload: {
196
+          body: response.body,
197
+          headers: normalize_response_headers(response.headers),
198
+          status: response.status
199
+        }
160 200
       end
161 201
     end
162 202
   end

+ 11 - 0
db/migrate/20160405072512_post_agent_set_event_header_style.rb

@@ -0,0 +1,11 @@
1
+class PostAgentSetEventHeaderStyle < ActiveRecord::Migration
2
+  def up
3
+    Agent.of_type("Agents::PostAgent").each do |post_agent|
4
+      if post_agent.send(:boolify, post_agent.options['emit_events']) &&
5
+         !post_agent.options.key?('event_headers_style')
6
+        post_agent.options['event_headers_style'] = 'raw'
7
+        post_agent.save!
8
+      end
9
+    end
10
+  end
11
+end

+ 20 - 2
spec/models/agents/post_agent_spec.rb

@@ -52,7 +52,7 @@ describe Agents::PostAgent do
52 52
           raise "unexpected Content-Type: #{content_type}"
53 53
         end
54 54
       end
55
-      { status: 200, body: "<html>a webpage!</html>", headers: { 'Content-Type' => 'text/html' } }
55
+      { status: 200, body: "<html>a webpage!</html>", headers: { 'Content-type' => 'text/html' } }
56 56
     }
57 57
   end
58 58
 
@@ -226,10 +226,28 @@ describe Agents::PostAgent do
226 226
           expect(@checker.events.last.payload['body']).to eq '<html>a webpage!</html>'
227 227
         end
228 228
 
229
-        it "emits the response headers" do
229
+        it "emits the response headers capitalized by default" do
230 230
           @checker.check
231 231
           expect(@checker.events.last.payload['headers']).to eq({ 'Content-Type' => 'text/html' })
232 232
         end
233
+
234
+        it "emits the response headers capitalized" do
235
+          @checker.options['event_headers_style'] = 'capitalized'
236
+          @checker.check
237
+          expect(@checker.events.last.payload['headers']).to eq({ 'Content-Type' => 'text/html' })
238
+        end
239
+
240
+        it "emits the response headers downcased" do
241
+          @checker.options['event_headers_style'] = 'downcased'
242
+          @checker.check
243
+          expect(@checker.events.last.payload['headers']).to eq({ 'content-type' => 'text/html' })
244
+        end
245
+
246
+        it "emits the response headers snakecased" do
247
+          @checker.options['event_headers_style'] = 'snakecased'
248
+          @checker.check
249
+          expect(@checker.events.last.payload['headers']).to eq({ 'content_type' => 'text/html' })
250
+        end
233 251
       end
234 252
     end
235 253
   end